package executor;

import java.io.*;

/**
 * Classe che fornisce funzioni di base per scrivere e leggere
 * un file binario, nel nostro caso contenente un quad-tree.
 * I nodi foglia sono rappresentati dal loro colore: tre byte
 * che vengono letti in (e scritti da) un intero.
 * I nodi interni sono rappresentati da un byte: il carattere
 * definito dalla costante NODE_CHAR nella classe QuadTree.
 * Questa classe fornisce i metodi per leggere e scrivere tali elementi.
 * Siccome in java i byte hanno il segno (rappresentano intervallo 
 * [-128,127]) e noi abbiamo valori di colore senza segno (in intervallo
 * [0,255]), prima di convertire da int a byte per scrivere sommiamo -128,
 * e nel leggere prima dopo convertito da byte a int sommiamo 128.
 * @see QuadColor
 * @see QuadTree
 */
public class BasicIO
{
  /** Legge un byte in binario e lo ritorna come numero intero.
   * @param in    il canale di input da cui legge
   * @return      il byte letto, come intero in [0,255]
   */
  public static int getByte(InputStream in) throws IOException
  {
    byte[] aux = new byte[1];
    in.read(aux,0,1);
    return 128 + (int)aux[0];
  }

  /** Legge tre byte in binario, li interpreta come le tre componenti
   * rosso, verde, blu di un colore e costruisce il colore su un intero.
   * @param in    il canale di input da cui legge
   * @return      il colore rappresentato su un singolo intero
   */
  public static int readRGB(InputStream in) throws IOException
  {
    int cc1, cc2, cc3;
    cc1 = getByte(in);
    cc2 = getByte(in);
    cc3 = getByte(in);
    return QuadColor.makeColor(cc1,cc2,cc3);
  }

  /** Dato un byte gia' letto, ne legge altri due, interpreta i tre byte
   * come le tre componenti rosso, verde, blu di un colore e costruisce
   * il colore su un intero.
   * @param in    il canale di input da cui legge
   * @param cc1   il valore intero del byte gia letto, in [0,255]
   * @return      il colore rappresentato su un singolo intero
   */
  public static int readRGB(InputStream in, int cc1) throws IOException
  {
    int cc2, cc3;
    cc2 = getByte(in);
    cc3 = getByte(in);
    return QuadColor.makeColor(cc1,cc2,cc3);
  }

  /** Dato un intero nell'intervallo rappresentabile su un solo byte, 
   * [0,255], scrive l'intero in binario su un byte. 
   * @param out    il canale di output su cui scrive
   */
  public static void putByte(OutputStream out, int val) throws IOException
  {  out.write( (byte)(val-128) );  }

  /** Dato un colore rappresentato su un numero intero (di cui sono usati 3 byte
   * per le tre componenti rosso, verde, blu), scrive il colore in binario
   * su tre byte.
   * @param out    il canale di output su cui scrive
   * @param rgb    il colore da scrivere rappresentato su un unico intero
   */
  public static void writeRGB(OutputStream out, int rgb) throws IOException
  {
    int red = QuadColor.getRed(rgb);
    int green = QuadColor.getGreen(rgb);
    int blue = QuadColor.getBlue(rgb);
    out.write( (byte)(red-128) );
    out.write( (byte)(green-128) );
    out.write( (byte)(blue-128) );    
  }

}
